/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package familytree.negocio.bo;

import com.sun.org.apache.bcel.internal.generic.ARRAYLENGTH;
import familytree.negocio.IArbolProcessor;
import familytree.persistencia.dao.ArbolDAO;
import familytree.persistencia.dao.DAOFactory;
import familytree.persistencia.dao.NodoDAO;
import familytree.persistencia.pojos.Album;
import familytree.persistencia.pojos.Arbol;
import familytree.persistencia.pojos.Nodo;
import familytree.persistencia.pojos.Pareja;
import familytree.persistencia.pojos.Usuario;
import familytree.util.INode;
import familytree.util.ITree;
import familytree.util.Tree;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author Antonio
 */
public class ArbolBO implements IArbolProcessor {

    private DAOFactory dAOFactory = DAOFactory.instance(DAOFactory.HIBERNATE);

    public Usuario iniciarFamilia(Arbol arbol, Nodo nodoHijo, Nodo nodoPadre, Nodo nodoMadre, Usuario usuario) {
        ArbolDAO arbolDAO = dAOFactory.getArbolDAO();
        Album album = new Album();
        album.setNombre("Sin clasificar");
        album.setComentario("Álbum por defecto");
        album.setFecha(Calendar.getInstance());
        return arbolDAO.iniciarFamila(arbol, nodoHijo, nodoPadre, nodoMadre, usuario, album);
    }

    public void setArbol(Arbol arbol) {
        ArbolDAO arbolDAO = dAOFactory.getArbolDAO();
        arbolDAO.makePersistent(arbol);
    }

    public void addArbol(Arbol arbol) {
        ArbolDAO arbolDAO = dAOFactory.getArbolDAO();
        arbolDAO.makePersistent(arbol);
    }

    public void anadirMadre(Pareja p, Nodo madre, Nodo hijo) {
        ArbolDAO arbolDao = dAOFactory.getArbolDAO();
        arbolDao.anadirMadre(p, madre, hijo);
    }

    public void anadirPadre(Pareja p, Nodo padre, Nodo hijo) {
        ArbolDAO arbolDao = dAOFactory.getArbolDAO();
        arbolDao.anadirPadre(p, padre, hijo);
    }

    public void anadirPareja(Nodo nodo, Nodo conyuje) {
        ArbolDAO arbolDao = dAOFactory.getArbolDAO();
        arbolDao.anadirPareja(nodo, conyuje);
    }

    public void anadirHijo(Nodo nodoActual, String idPareja, Nodo nodoHijo) {
        ArbolDAO arbolDao = dAOFactory.getArbolDAO();

        Nodo hijo = arbolDao.anadirHijo(nodoActual, idPareja, nodoHijo);


    }

    public void addComponentes(List<Nodo> lista) {
        ArbolDAO arbolDao = dAOFactory.getArbolDAO();
        arbolDao.addComponentes(lista);
    }

    public void invitarFamiliar(String direccionDestino, String mensaje, String idNodo, String clave, String nombreMiembro) {

        int n = CorreoBO.sendCorreo(direccionDestino, mensaje, idNodo, clave, nombreMiembro);
    }

    public ITree[] createTrees(Nodo nodo) {
        ITree[] familia = new ITree[2];
        ITree ascendentes = createAscendetes(nodo);
        ITree descendencia = createDescendentes(nodo);


        familia[0] = ascendentes;
        familia[1] = descendencia;

        return familia;
    }

    private ITree addRestoFamilia(ITree ascendentes, INode children, Nodo nodoPojo, boolean anadirHijos) {

        ITree arbolResultado = ascendentes;
        StringBuffer sb = new StringBuffer("");
        String valorAcual = children.getValor();
        int indice = 0;
        boolean seAnadioPadre = false, seAnadioMadre = false;
        Nodo padrePojo = null, madrePojo = null;
        if (nodoPojo.getPadres() != null) {
            padrePojo = nodoPojo.getPadres().getComponente1();
            if (padrePojo != null) {
                if ((valorAcual.equals(ArbolConstant.TUPADRE)) || (valorAcual.equals(ArbolConstant.TUMADRE))) {
                    sb = sb.append(ArbolConstant.TUABUELO);
                } else {
                    sb = sb.append(ArbolConstant.ELPADRE);
                    sb = sb.append(" " + valorAcual);
                }
                seAnadioPadre = arbolResultado.addChildren(children, padrePojo.getIdNodo(), sb.toString());
            }

            sb = new StringBuffer("");
            if (nodoPojo.getPadres().getComponente2() != null) {
                madrePojo = nodoPojo.getPadres().getComponente2();
                if ((valorAcual.equals(ArbolConstant.TUPADRE)) || (valorAcual.equals(ArbolConstant.TUMADRE))) {
                    sb = sb.append(ArbolConstant.TUABUELA);
                } else {
                    sb = sb.append(ArbolConstant.LAMADRE);
                    sb = sb.append(" " + valorAcual);
                }
                seAnadioMadre = arbolResultado.addChildren(children, madrePojo.getIdNodo(), sb.toString());

            }

            if (seAnadioPadre) {
                arbolResultado = addRestoFamilia(arbolResultado, children.getChildren(indice), padrePojo, true);
                indice++;
            }
            if (seAnadioMadre) {
                arbolResultado = addRestoFamilia(arbolResultado, children.getChildren(indice), madrePojo, true);
                indice++;
            }



        }
        if (anadirHijos) {
            arbolResultado = addHijosTree(ascendentes, children, nodoPojo, indice);
        }
        return arbolResultado;

    }

    private String[] aumentaArray(String[] ruta) {
        String[] resultado = new String[ruta.length + 1];
        for (int i = 0; i < ruta.length; i++)
            resultado[i] = ruta[i]; 
        return resultado;
    }

    private ITree createAscendetes(Nodo nodoUsuario) {

        ITree ascendentes = new Tree();
        ascendentes.setRoot(nodoUsuario.getIdNodo(), ArbolConstant.TU);
        INode inode = ascendentes.getRoot();
        int indice = 0;
        Nodo padre = null, madre = null;
        boolean seAnadioPadre = false, seAnadioMadre = false;
        if (nodoUsuario.getPadres() != null) {
            if (nodoUsuario.getPadres().getComponente1() != null) {
                padre = nodoUsuario.getPadres().getComponente1();
                seAnadioPadre = ascendentes.addChildren(inode, padre.getIdNodo(), ArbolConstant.TUPADRE);


            }
            if (nodoUsuario.getPadres().getComponente2() != null) {
                madre = nodoUsuario.getPadres().getComponente2();
                seAnadioMadre = ascendentes.addChildren(inode, madre.getIdNodo(), ArbolConstant.TUMADRE);

            }
        }

        if (seAnadioPadre) {
            ascendentes = addRestoFamilia(ascendentes, inode.getChildren(indice), padre, true);
            indice++;
        }
        if (seAnadioMadre) {
            ascendentes = addRestoFamilia(ascendentes, inode.getChildren(indice), madre, true);
        }
        return ascendentes;
    }

    private ITree createDescendentes(Nodo raiz) {

        ITree descendentes = new Tree();

        descendentes.setRoot(raiz.getIdNodo(), ArbolConstant.TU);
        INode raizArbol = descendentes.getRoot();
        descendentes = addHijosTree(descendentes, raizArbol, raiz, 0);


        return descendentes;

    }

    private ITree addHijosTree(ITree arbolResultado, INode children, Nodo nodoPojo, int indice) {

        String valorActual = children.getValor();
        StringBuffer sb = new StringBuffer("");
        ITree arbol = arbolResultado;
        Set<Pareja> parejas = nodoPojo.getParejas();
        for (Pareja par : parejas) {
            Set<Nodo> hijos = par.getHijos();
            for (Nodo nodo : hijos) {
                sb = ArbolConstant.getValorHijo(valorActual, nodo.getSexo());
                if (arbol.addChildren(children, nodo.getIdNodo(), sb.toString())) {
                    arbol = addHijosTree(arbolResultado, children.getChildren(indice), nodo, 0);
                    indice++;
                }
            }
        }

        return arbol;
    }

    public String[][] getruta(Nodo nodo, ITree[] familia) {
        String[] rutaNombres = new String[0];
        String[] rutaId = new String[0];
        String[][] ruta = new String[2][0];
        ruta = getRutaRecursiva(nodo, familia, true);
        if (ruta[0].length == 0){
            
            rutaNombres = new String[2];
            rutaNombres[0] = ArbolConstant.TU;
            rutaNombres[1] = ArbolConstant.FAMILIARLEJANO;
            rutaId = new String[2];
            rutaId[0] = familia[0].getRoot().getIdentificador();
            rutaId[1] = nodo.getIdNodo();
            ruta[0] = rutaNombres;
            ruta[1] = rutaId;
            
        }    
        return ruta;
    }
    private String[][] getRutaRecursiva(Nodo nodo, ITree[] familia, boolean recursividad){
        String[][] ruta = new String[2][0];
        String[] rutaNombre = new String[0];
        String[] rutaId = new String[0];
        String aux = familia[0].findNode(nodo.getIdNodo());
        if (!aux.contains(Tree.NOENCONTRADO)) {
            String[] camino = aux.split("-");
            ruta = familia[0].getValores(camino);
        } else {
            aux = familia[1].findNode(nodo.getIdNodo());
            if (!aux.contains(Tree.NOENCONTRADO)) {
                String[] camino = aux.split("-");
                ruta = familia[1].getValores(camino);
            }
        }
        if (ruta[0].length == 0 && recursividad){
            Set<Pareja> parejas = new HashSet<Pareja>();
            for (Pareja p: (Set<Pareja>)nodo.getParejas()){
                parejas.add(p);
            }
            parejas.addAll((Set<Pareja>)nodo.getParejasComoComponenteDos());
            Nodo nodoAux;
            for (Pareja pareja : parejas) {
                if (pareja.getComponente2() != null && pareja.getComponente1() != null){
                    if (pareja.getComponente1().getIdNodo().equals(nodo.getIdNodo()))
                        nodoAux = pareja.getComponente2();
                    else
                        nodoAux = pareja.getComponente1();
                    ruta = getRutaRecursiva(nodoAux, familia, false);
                    int longitud = ruta[0].length;
                    if (longitud != 0){
                        String[] rutaNueva = new String[longitud + 1];
                        
                        if (longitud > 1){
                            rutaNueva = aumentaArray(ruta[0]);
                            rutaNueva[longitud] = ArbolConstant.LAPAREJA + " " +ruta[0][longitud - 1];
                            
                            
                        }
                        else{
                            rutaNueva[longitud] = ArbolConstant.TUPAREJA;
                            rutaNueva[0] = ruta[0][0];
                        }
                        ruta[1] = aumentaArray(ruta[1]);
                        ruta[1][longitud] = nodo.getIdNodo();
                        ruta[0] = rutaNueva;
                        break;
                    }                    
                }
            }
        }
        return ruta;
    }

    public List<Nodo> findNodosByName(String nombre, String primerApellido, String segundoApellido) {
        
        BusquedaBO<Nodo> busquedaBO = new BusquedaBO<Nodo>(new StrategyBusquedaNodoPorNombreYApellidosBO());
        return busquedaBO.buscar(nombre, primerApellido, segundoApellido);
    }

    public List<Nodo> findNodosByArbol(String idArbol) {
        ArbolDAO arbolDAO = dAOFactory.getArbolDAO();
        return arbolDAO.findNodosByIdArbol(idArbol);
    }

    public List<Nodo> findNodoByCompleteName(String nombre, String idArbol) {
        
        ArbolDAO arbolDAO = dAOFactory.getArbolDAO();
        return arbolDAO.findNodosByCompleteName(nombre,idArbol);
    }

}
